package org.openjava.jsonbuilder;

import java.util.LinkedList;
import java.util.List;

import org.openjava.utils.ReflectionUtils;

public class PojoNode {
	private String nodeName;
	private String quatifiedName;
	private List<PojoNode> children = new LinkedList<PojoNode>();
	private Object element;
	private PojoNode parent;
	private StringBuffer buffer;
	private PojoNodeConfig config  = null;
	
	
	public PojoNode(String nodeName,Object element,String quatifiedName){
		this.nodeName = nodeName;
		this.element = element;
		this.quatifiedName = quatifiedName;
	}
	
	public PojoNode addChild(PojoNode node,PojoTree tree){
		tree.initTree(node);
		node.setParent(this);
		node.setConfig(tree.getConfig());
		children.add(node);
		return node;
	}
	
	public boolean removeChild(PojoNode node){
		return this.children.remove(node);
	}
	public PojoNode addChild(String nodeName,Object element,PojoTree tree){
		String quatifiedName = null;
		if(this.getQuatifiedName().equals("")){
			quatifiedName = this.getQuatifiedName() + nodeName;
		}else{
			quatifiedName = this.getQuatifiedName() + "." +nodeName;
		}
		if(tree.getConfig() == null || tree.getConfig().isIncluded(quatifiedName)){
			return addChild(new PojoNode(nodeName,element,quatifiedName),tree);
		}
		return null;
		
	}
	
	public PojoNode nextSibling(){
		List<PojoNode> parentChildRen = this.getParent().getChildren();
		int index = parentChildRen.indexOf(this);
		return parentChildRen.get(keepInRange(index, 1));
	}
	
	private int keepInRange(int index,int change){
		int dir = index + change;
		int csize = this.children.size();
		return dir >= csize? dir - csize:(dir < 0? (csize - dir):(dir));
	}
	
	
	public PojoNode previousSibling(){
		List<PojoNode> parentChildRen = this.getParent().getChildren();
		int index = parentChildRen.indexOf(this);
		return parentChildRen.get(keepInRange(index, -1));
	}
	public List<PojoNode> getChildren() {
		return children;
	}
	
	public String toJSON(){
		if(this.getParent() == null || this.getParent().getBuffer() == null){
			this.buffer = new StringBuffer();
			this.getParent().setBuffer(buffer);
		}else
			this.buffer = this.getParent().getBuffer();
		privateToJson(buffer);
		return buffer.toString();
	}
	
	private void privateToJson(StringBuffer buffer){
		String quote = config == null?"\"":config.getQuote();
		buffer.append(quote).append(this.nodeName).append(quote).append(":");
		if(this.element.getClass().isArray()){
			buffer.append(JSONBuilder.fromArray(this.element));
		}else{
			if(ReflectionUtils.isJSONMinObj(this.element)){
				buffer.append(JSONBuilder.fromObject(this.element));
			}else{
				buffer.append("{");
				for(PojoNode node:this.children){
					node.toJSON();
					buffer.append(",");
				}
				buffer.deleteCharAt(buffer.length() -1);
				buffer.append("}");
			}
		}
	}
	
	public Object getElement() {
		return element;
	}
	
	public String getNodeName() {
		return nodeName;
	}
	
	public String getQuatifiedName() {
		return quatifiedName;
	}
	
	public void setQuatifiedName(String quatifiedName) {
		this.quatifiedName = quatifiedName;
	}

	public PojoNode getParent() {
		return parent;
	}

	public void setParent(PojoNode parent) {
		this.parent = parent;
	}

	public void setNodeName(String nodeName) {
		this.nodeName = nodeName;
	}

	public void setChildren(List<PojoNode> children) {
		this.children = children;
	}
	
	public StringBuffer getBuffer() {
		return buffer;
	}
	
	public void setBuffer(StringBuffer buffer) {
		this.buffer = buffer;
	}
	
	 
	public PojoNodeConfig getConfig() {
		return config;
	}

	public void setConfig(PojoNodeConfig config) {
		this.config = config;
	}

	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return this.quatifiedName + this.element + this.children;
	}
}
